package ntlmssp

import (
	
	
	
	
	
	
)

// GetDomain : parse domain name from based on slashes in the input
// Need to check for upn as well
func ( string) (string, string, bool) {
	 := ""
	 := false

	if strings.Contains(, "\\") {
		 := strings.SplitN(, "\\", 2)
		 = [0]
		 = [1]
		 = true
	} else if strings.Contains(, "@") {
		 = false
	} else {
		 = true
	}
	return , , 
}

//Negotiator is a http.Roundtripper decorator that automatically
//converts basic authentication to NTLM/Negotiate authentication when appropriate.
type Negotiator struct{ http.RoundTripper }

//RoundTrip sends the request to the server, handling any authentication
//re-sends as needed.
func ( Negotiator) ( *http.Request) ( *http.Response,  error) {
	// Use default round tripper if not provided
	 := .RoundTripper
	if  == nil {
		 = http.DefaultTransport
	}
	// If it is not basic auth, just round trip the request as usual
	 := authheader(.Header.Values("Authorization"))
	if !.IsBasic() {
		return .RoundTrip()
	}
	 := .Basic()
	// Save request body
	 := bytes.Buffer{}
	if .Body != nil {
		_,  = .ReadFrom(.Body)
		if  != nil {
			return nil, 
		}

		.Body.Close()
		.Body = ioutil.NopCloser(bytes.NewReader(.Bytes()))
	}
	// first try anonymous, in case the server still finds us
	// authenticated from previous traffic
	.Header.Del("Authorization")
	,  = .RoundTrip()
	if  != nil {
		return nil, 
	}
	if .StatusCode != http.StatusUnauthorized {
		return , 
	}
	 := authheader(.Header.Values("Www-Authenticate"))
	if !.IsNegotiate() && !.IsNTLM() {
		// Unauthorized, Negotiate not requested, let's try with basic auth
		.Header.Set("Authorization", string())
		io.Copy(ioutil.Discard, .Body)
		.Body.Close()
		.Body = ioutil.NopCloser(bytes.NewReader(.Bytes()))

		,  = .RoundTrip()
		if  != nil {
			return nil, 
		}
		if .StatusCode != http.StatusUnauthorized {
			return , 
		}
		 = authheader(.Header.Values("Www-Authenticate"))
	}

	if .IsNegotiate() || .IsNTLM() {
		// 401 with request:Basic and response:Negotiate
		io.Copy(ioutil.Discard, .Body)
		.Body.Close()

		// recycle credentials
		, ,  := .GetBasicCreds()
		if  != nil {
			return nil, 
		}

		// get domain from username
		 := ""
		, ,  := GetDomain()

		// send negotiate
		,  := NewNegotiateMessage(, "")
		if  != nil {
			return nil, 
		}
		if .IsNTLM() {
			.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString())
		} else {
			.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString())
		}

		.Body = ioutil.NopCloser(bytes.NewReader(.Bytes()))

		,  = .RoundTrip()
		if  != nil {
			return nil, 
		}

		// receive challenge?
		 = authheader(.Header.Values("Www-Authenticate"))
		,  := .GetData()
		if  != nil {
			return nil, 
		}
		if !(.IsNegotiate() || .IsNTLM()) || len() == 0 {
			// Negotiation failed, let client deal with response
			return , nil
		}
		io.Copy(ioutil.Discard, .Body)
		.Body.Close()

		// send authenticate
		,  := ProcessChallenge(, , , )
		if  != nil {
			return nil, 
		}
		if .IsNTLM() {
			.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString())
		} else {
			.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString())
		}

		.Body = ioutil.NopCloser(bytes.NewReader(.Bytes()))

		return .RoundTrip()
	}

	return , 
}